/***********************************************************************************************************************
**	filename: main.c
**	author: Echo Zhang @2021-02-04
**  e-mail: not_xx@126.com
***********************************************************************************************************************/

#include "user_types.h"
#include "dbg.h"
#include "net_server.h"

#include <uv.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

static NetServer_ST _Server;
static NetServer_ST _Client;

static ui16 _ServerPort = 0;
static bool _ServerIsTcp = false;
static ui16 _ClientPort = 0;
static bool _ClientIsTcp = false;
static ui32 _PacketSize = 65536;

static void _print_usage(const char *appName)
{
    std_printf("usage: %s [-m uu/ut/tu/tt -s packetSize] sPort cPort\n", appName);
    std_printf("-m: mode, uu:udp-udp, ut:udp-tcp, tu:tcp-udp, tt:tcp-tcp\n");
    std_printf("packetSize: >= 1, default: %u\n", _PacketSize);
}

static ui16 _conv_str_to_ui16(const char *str, bool *ok)
{
    unsigned long int value = strtoul(str, NULL, 10);
    *ok = value <= 0xFFFF;
    return (ui16)value;
}
static ui16 _conv_str_to_ui32(const char *str, bool *ok)
{
    unsigned long int value = strtoul(str, NULL, 10);
    *ok = value <= 0xFFFFFFFF;
    return (ui32)value;
}

static bool _parse_tcp_mode(char ch, bool *ok)
{
    bool isTcp = (ch == 't');
    *ok = isTcp || (ch == 'u');
    if(!(*ok)) {
        std_printf("unkown net type: %c\n", ch);
    }
   return isTcp;
}

static bool _parse_args(int argc, char *argv[])
{
    int ret;
    bool ok;

    while((ret=getopt(argc, argv, "m:s:")) >= 0) {
        switch(ret) {
        case 'm':
            if(optarg == NULL || strlen(optarg) != 2) {
                return false;
            }
            _ServerIsTcp = _parse_tcp_mode(optarg[0], &ok);
            if(!ok) {
                return false;
            }
            _ClientIsTcp = _parse_tcp_mode(optarg[1], &ok);
            if(!ok) {
                return false;
            }
            break;
        case 's':
            if(optarg == NULL) {
                return false;
            }
            _PacketSize = _conv_str_to_ui32(optarg, &ok);
            if(!ok || _PacketSize <= 0) {
                return false;
            }
            break;
        default:
            std_printf("unkown args: %c %s", (char)ret, optarg);
            return false;
        }
    }
    if(argc-optind != 2) {
        return false;
    }
    _ServerPort = _conv_str_to_ui16(argv[optind], &ok);
    if(!ok || _ServerPort==0) {
        return false;
    }
    _ClientPort = _conv_str_to_ui16(argv[optind+1], &ok);
    if(!ok || _ClientPort==0) {
        return false;
    }
    return true;
}

static void _recv_net_data(NetServer_ST *server, const ui8 data[], Size_DT dataLen)
{
    net_server_send_udp_data((server->data), data, dataLen);
}

int main(int argc, char *argv[])
{
    if(!_parse_args(argc, argv)) {
        _print_usage(argv[0]);
        return -1;
    }
    // dbg_print_uint(_PacketSize);
    // dbg_print_uint(_ServerIsTcp);
    // dbg_print_uint(_ServerPort);
    // dbg_print_uint(_ClientPort);
    // dbg_print_uint(_ClientIsTcp);
    net_server_init(&_Server, _recv_net_data, _PacketSize);
    net_server_init(&_Client, _recv_net_data, _PacketSize);
    _Server.data = &_Client;
    _Client.data = &_Server;

    net_server_start(&_Server, _ServerPort);
    net_server_start(&_Client, _ClientPort);

    return uv_run(uv_default_loop(), UV_RUN_DEFAULT);
}

/***********************************************************************************************************************
**	endline
***********************************************************************************************************************/
